package org.qing.cloud.commons.config.redis;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory;
import org.springframework.data.redis.core.ReactiveRedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;

@Configuration
public class ReactiveRedisConfig {

	@Bean
	@Primary
	public ReactiveRedisTemplate<String, Object> reactiveRedisTemplate(ReactiveRedisConnectionFactory factory) {
		RedisSerializer<Object> redisSerializer = redisSerializer();
		RedisSerializationContext<String, Object> context = redisSerializationContext(redisSerializer);
		return new ReactiveRedisTemplate<String, Object>(factory, context);
	}

	private RedisSerializer<Object> redisSerializer() {
		// 自定义redis序列化的机制,重新定义一个ObjectMapper.防止和MVC的冲突
		ObjectMapper objectMapper = new ObjectMapper();
		// 反序列化时候遇到不匹配的属性并不抛出异常
		objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
		// 序列化时候遇到空对象不抛出异常
		objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
		// 反序列化的时候如果是无效子类型,不抛出异常
		objectMapper.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false);
		// 不使用默认的dateTime进行序列化,
		objectMapper.configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS, false);
		// 使用JSR310提供的序列化类,里面包含了大量的JDK8时间序列化类
		objectMapper.registerModule(new JavaTimeModule());
		// 启用反序列化所需的类型信息,在属性中添加@class
		//objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL,
		//		JsonTypeInfo.As.PROPERTY);
		// 配置null值的序列化器
		GenericJackson2JsonRedisSerializer.registerNullValueSerializer(objectMapper, null);
		return new GenericJackson2JsonRedisSerializer(objectMapper);
	}

	private RedisSerializationContext<String, Object> redisSerializationContext(
			RedisSerializer<Object> redisSerializer) {
		return new RedisSerializationContext<String, Object>() {
			private SerializationPair<String> getStringPair() {
				// 字符串处理
				SerializationPair<String> serializationPair = SerializationPair
						.fromSerializer(StringRedisSerializer.UTF_8);
				return serializationPair;
			}

			private SerializationPair<Object> getObjectPair() {
				// 对象处理
				SerializationPair<Object> serializationPair = SerializationPair.fromSerializer(redisSerializer);
				return serializationPair;
			}

			@Override
			public SerializationPair<String> getKeySerializationPair() {
				return getStringPair();
			}

			@Override
			public SerializationPair<Object> getValueSerializationPair() {
				return getObjectPair();
			}

			@Override
			public SerializationPair<Object> getHashKeySerializationPair() {
				return getObjectPair();
			}

			@Override
			public SerializationPair<Object> getHashValueSerializationPair() {
				return getObjectPair();
			}

			@Override
			public SerializationPair<String> getStringSerializationPair() {
				return getStringPair();
			}
		};
	}
}
